package com.augurit.common.system.service.org.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.orm.Page;

import com.augurit.common.constant.OrgConstant;
import com.augurit.common.dao.AcFunctionDao;
import com.augurit.common.dao.AcMenuDao;
import com.augurit.common.entity.AcMenu;
import com.augurit.common.system.convert.AcMenuConverter;
import com.augurit.common.system.service.org.IAcMenuService;
import com.augurit.common.system.service.org.IAcRoleService;
import com.augurit.common.system.util.OrgUtils;
import com.augurit.common.system.web.auth.form.LoginUserForm;
import com.augurit.common.system.web.org.form.AcMenuForm;
import com.augurit.common.system.web.org.form.AtHomepageConfigForm;
import com.augurit.common.util.HqlUtils;
import com.augurit.common.util.PageUtils;
import com.augurit.common.util.lang.StringUtils;

@Service
@Transactional
public class AcMenuServiceImpl implements IAcMenuService{
	
	// DAO 引用
	@Autowired
	private AcMenuDao acMenuDao;
	
	@Autowired
	private AcFunctionDao acFunctionDao;
	
	@Autowired
	private IAcRoleService acRoleService;
	
	
	@Transactional(readOnly = true)
	public List getMenusByMenuLevel(LoginUserForm loginUser, AtHomepageConfigForm atHomepageConfigForm){
		int loadMenuLevel = atHomepageConfigForm.getLoadMenuLevel().intValue();
		String loadByTree = atHomepageConfigForm.getLoadByTree();
		String modelName = atHomepageConfigForm.getModelName();
		return getMenusByMenuLevel(loginUser, loadMenuLevel, loadByTree, modelName, true);
	}
	
	@Transactional(readOnly = true)
	public List getMenusByMenuLevel(int loadMenuLevel, String loadByTree, String modelName){
		return getMenusByMenuLevel(null, loadMenuLevel, loadByTree, modelName, false);
	}
	

	@Transactional(readOnly = true)
	public List<AcMenuForm> getMenusByMenuLevel(LoginUserForm loginUser, int loadMenuLevel, String loadByTree){
		return getMenusByMenuLevel(loginUser, loadMenuLevel, loadByTree, AcMenuForm.class.getSimpleName(), true);
	}
	
	@Transactional(readOnly = true)
	public List getMenusByMenuLevel(LoginUserForm loginUser, int loadMenuLevel, String loadByTree, String modelName, boolean onlyActiveMenu){
		List result = null;
		
		if(loadMenuLevel > 0 && modelName != null && modelName.trim().length() > 0){
			//加载菜单数据
			List<AcMenu> list = getByMenuLevel(loginUser, loadMenuLevel, onlyActiveMenu);
			//转换为指定的Ext对象
			result = AcMenuConverter.convertByNodeType(modelName, list, (loadByTree != null && loadByTree.equals(OrgConstant.ONE) ? true : false));
		}
		
		return result;
	}
	
	@Transactional(readOnly = true)
	private List<AcMenu> getByMenuLevel(LoginUserForm loginUser, int loadMenuLevel, boolean onlyActiveMenu){
		List<AcMenu> result = null;
		
		if(loadMenuLevel > 0){			
			//加载菜单数据
			String hql = "from AcMenu ps where 1=1"
				+ (onlyActiveMenu ? " and ps.isActive='" + OrgConstant.ONE + "'" : "")
				+ OrgUtils.getPrivilegeWhereClause("ps", loginUser)
				+ OrgUtils.getMenuLevelWhereClause("ps", loadMenuLevel)
				+ " order by ps.menuLevel asc, ps.sortNo asc";
			result = acMenuDao.find(hql);
		}
		
		return result;
	}
	
	
	
	/**
	 * 获取指定菜单对应的功能id
	 * @param menuId 菜单id 
	 * @return 功能id
	 */
	public Long getRelatedFuncIdByMenuId(Long menuId){
		if( menuId != null)
			return acMenuDao.getRelatedFuncIdByMenuId(menuId);
		return null;
	}

	/**
	 * 根据功能ID集合获取关联的菜单ID集合
	 * 注意：如果某菜单存在父菜单，则同时也会返回其所有关联的父菜单列表
	 * @param funcIds
	 * @return
	 */
	public Long[] getAllRelatedMenuIds(Long[] funcIds){
		return acMenuDao.getAllRelatedMenuIds(funcIds);
	}
	
	@Transactional(readOnly = true)
	public List getChildTree(Long parentMenuId, String modelName){
		return getChildTree(null, parentMenuId, 1, modelName, false);
	}
	
	@Transactional(readOnly = true)
	public List<AcMenuForm> getChildTree(LoginUserForm loginUser, Long parentMenuId, int depth){
		return getChildTree(loginUser, parentMenuId, depth, AcMenuForm.class.getSimpleName(), true);
	}
	
	@Transactional(readOnly = true)
	public List getChildTree(LoginUserForm loginUser, Long parentMenuId, int depth, String modelName, boolean onlyActiveMenu){
		List result = null;
		
		if(parentMenuId != null){
			List<AcMenu> list = null;
			
			if(parentMenuId.intValue() < 0)
				list = getChildrenByDepth(loginUser, null, 1, onlyActiveMenu);	//如果父节点ID为-1，则表示获取一级菜单节点
			else
				list = getChildrenByDepth(loginUser, parentMenuId, depth, onlyActiveMenu);
			
			//转换为指定的Ext对象
			result = AcMenuConverter.convertByNodeType(modelName, list, depth);
		}
		
		return result;
	}

	@Transactional(readOnly = true)
	private List<AcMenu> getChildrenByDepth(LoginUserForm loginUser, Long parentMenuId, int depth, boolean onlyActiveMenu){
		List<AcMenu> result = null;
		
		if(depth > 0){
			
			//获取父菜单菜单层次
			int parentMenuLevel = this.getMenuLevel(parentMenuId);
			
			//加载菜单数据
			String hql = "from AcMenu ps where 1=1"
				+ (onlyActiveMenu ? " and ps.isActive='" + OrgConstant.ONE + "'" : "")
				+ OrgUtils.getPrivilegeWhereClause("ps", loginUser)
				+ OrgUtils.getMenuDepthWhereClause("ps", parentMenuLevel, depth)
				+ OrgUtils.getParentMenuAndChildrenWhereClause("ps", parentMenuId, false)
				+ " order by ps.menuLevel asc, ps.sortNo asc";
			result = acMenuDao.find(hql);
		}
		
		return result;
	}
	
	/**
	 * 根据菜单对象主键ID获取菜单层次
	 * @param menuId 菜单对象主键ID
	 * @return 正整数的菜单层次，如为-1则表示指定菜单对象不存在或菜单属性为空。
	 */
	@Transactional(readOnly = true)
	public int getMenuLevel(Long menuId){
		if(menuId != null){
			AcMenu entity = acMenuDao.findUniqueBy("menuId", menuId);
			if(entity != null && entity.getMenuLevel() != null)
				return entity.getMenuLevel().intValue();
		}
		
		return -1;
	}
	
	@Transactional(readOnly = true)
	public AcMenuForm get(Long menuId){
		AcMenuForm form = null;
		
		if(menuId != null){
			AcMenu entity = acMenuDao.get(menuId);
			form = AcMenuConverter.convertToForm(entity, false);
			
			if(entity.getParentMenuId() != null)
				form.setParentMenuName(this.get(entity.getParentMenuId()).getMenuName());
			
			if(entity.getFuncId() != null)
				form.setFuncName(acFunctionDao.get(entity.getFuncId()).getFuncName());
		}
		return form;
	}

	/**
	 * 保存业务字典项Form对象
	 * @param form Form对象
	 */
	public void save(AcMenuForm form){
		acMenuDao.save(form);
	}
	
	/**
	 * 保存业务字典项Form对象数组
	 * @param forms Form对象数组
	 */
	public void save(AcMenuForm... forms){
		if(forms != null)
			for(AcMenuForm form : forms)
				acMenuDao.save(form);
	}
	
	/**
	 * 保存业务字典项Form对象数组
	 * @param forms Form对象数组
	 */
	public void saveCascade(AcMenuForm... forms){
		if(forms != null)
			for(AcMenuForm form : forms)
				acMenuDao.saveCascade(form);
	}
	
	/**
	 * 根据主键ID集合删除多个业务字典项对象
	 * @param ids 业务字典项主键ID集合
	 */
	public void delete(Long... ids) {
		if(ids != null)
			acMenuDao.delete(ids);
	}
	
	/**
	 * 级联删除菜单
	 * @param menuId
	 */
	public void deleteMenuCasCade(Long menuId){
		acMenuDao.deleteMenuCasCade(menuId);
	}
	
	/**
	 * 级联删除菜单
	 * @param menuIds
	 */
	public void deleteMenuCasCade(Long... menuIds){
		if(menuIds != null){
			for(Long menuId:menuIds){
				acMenuDao.deleteMenuCasCade(menuId);
			}
		}
	}
	
	/**
	 * 分页显示所有的角色列表
	 * @param page page对象
	 * @return
	 */
	@Transactional(readOnly = true)
	public Page<AcMenuForm> getAllMenus(Page<AcMenuForm> page){
		return getAllMenus(page, null);
	}
	
	@Transactional(readOnly = true)
	public Page<AcMenuForm> getAllMenus(Page<AcMenuForm> page, AcMenuForm form){
		Page<AcMenu> pg = PageUtils.newPageInstance(page);
		
		// 按过滤条件分页查找对象
		StringBuffer hql = new StringBuffer("from AcMenu menu where 1=1");
		List values = new ArrayList();
		
		// 构造查询条件
		buildQueryCondition(hql, values, form);

		// 排序
		hql.append(" order by menu.menuLevel asc, menu.sortNo asc");
		
		acMenuDao.findPage(pg, hql.toString(), values);
		
		// 转换为Form对象列表并赋值到原分页对象中
		List<AcMenuForm> list = AcMenuConverter.convertToForm(pg.getResult());
		
		//为菜单Form对象列表加载关联功能名称
		acFunctionDao.loadFuncName(list);
		
		PageUtils.copy(pg, list, page);
		return page;
	}
	
	
	/**
	 * 获取系统中所有与功能点关联的菜单
	 * @param page 分页对象
	 * @param form f
	 * @return
	 */
	@Transactional(readOnly = true)
	public Page<AcMenuForm> getAllMenusAssociateFunc(Page<AcMenuForm> page, AcMenuForm form){
		// 建立新的分页对象
		Page<AcMenu> pg = PageUtils.newPageInstance(page);
		
		// 按过滤条件分页查找对象
		StringBuffer hql = new StringBuffer("from AcMenu ps where ps.funcId is not null");
		List values = new ArrayList();
		
		buildQueryCondition(hql, values, form);

		// 排序
		if( StringUtils.isNotBlank(page.getOrderBy().trim()) ){
			String orderBy = HqlUtils.buildOrderBy(page, "ps");
			hql.append(orderBy);
		}
		else
			hql.append(" order by ps.menuLevel asc, ps.sortNo asc");
		
		pg = acMenuDao.findPage(pg, hql.toString(), values);
		
		// 转换为Form对象列表并赋值到原分页对象中
		List<AcMenuForm> list = AcMenuConverter.convertToForm(pg.getResult());
		PageUtils.copy(pg, list, page);
		return page;
	}
	
	@Transactional(readOnly = true)
	public List<AcMenuForm> searchMenu(LoginUserForm loginUser, AcMenuForm form){
		// 按过滤条件分页查找对象
		StringBuffer hql = new StringBuffer("from AcMenu ps where 1=1 ");
		hql.append(OrgUtils.getPrivilegeWhereClause("ps", loginUser));
		
		List values = new ArrayList();
		
		//构造查询条件
		buildQueryCondition(hql, values, form);
		
		//排序
		hql.append(" order by ps.menuLevel asc, ps.sortNo asc");
		
		List<AcMenu> list = acMenuDao.find(hql.toString(), values);
		
		return AcMenuConverter.convertToForm(list);
	}
	
	/**
	 * 构造查询条件
	 * @param hql
	 * @param values
	 * @param form
	 */
	private void buildQueryCondition(StringBuffer hql, List values, AcMenuForm form){
		if(form != null){
			if(form.getMenuCode() != null && form.getMenuCode().trim().length() > 0){
				hql.append(" and menu.menuCode like ?");
				values.add("%" + form.getMenuCode() + "%");
			}
			if(form.getMenuName() != null && form.getMenuName().trim().length() > 0){
				hql.append(" and menu.menuName like ?");
				values.add("%" + form.getMenuName() + "%");
			}
			if(form.getMenuLevel() != null){
				hql.append(" and menu.menuLevel = ?");
				values.add(form.getMenuLevel());
			}
			if(form.getIsLeaf() != null && form.getIsLeaf().trim().length() > 0){
				hql.append(" and menu.isLeaf = ?");
				values.add(form.getIsLeaf());
			}
			if(form.getIsActive() != null && form.getIsActive().trim().length() > 0){
				hql.append(" and menu.isActive = ?");
				values.add(form.getIsActive());
			}			
		}
		
	}
	
	/**
	 * 给定一些菜单的id,获取（非叶子）菜单列表
	 * @param menuIds
	 * @return
	 */
	public List<AcMenuForm> getMenusInMenuIds(Long[] menuIds){
		if( menuIds != null && menuIds.length > 0){
			
			String hql = "from AcMenu ps where ps.isLeaf=" + "1 ";
			String condition = HqlUtils.buildOrCondition("ps", "menuId", menuIds);
			hql += "and ";
			hql += condition;
			
			List<AcMenu> enities = acMenuDao.find(hql);
			
			// 转换为Form对象列表并赋值到原分页对象中
			List<AcMenuForm> list = AcMenuConverter.convertToForm(enities);
			return list;
			
		}
		return null;
	}
	
	
	/**
	 * 给定一些菜单的id，分页查询在其中的菜单
	 * @param page 分页对象
	 * @param menuIds 菜单数组
	 * @return 分页对象
	 */
	public Page<AcMenuForm> getMenusInMenuIds(Page<AcMenuForm> page, Long[] menuIds){
		if( menuIds != null && menuIds.length > 0){
			// 建立新的分页对象
			Page<AcMenu> pg = PageUtils.newPageInstance(page);
			
			String hql = "from AcMenu ps where ps.isLeaf=" + "1 ";
			String condition = HqlUtils.buildOrCondition("ps", "menuId", menuIds);
			hql += "and ";
			hql += condition;
			
			pg = acMenuDao.findPage(pg, hql);
			
			// 转换为Form对象列表并赋值到原分页对象中
			List<AcMenuForm> list = AcMenuConverter.convertToForm(pg.getResult());
			PageUtils.copy(pg, list, page);
			return page;
			
		}
		return null;
	}
	
	/**
	 * 给定一些菜单的id，分页查询不在其中的菜单
	 * @param page 分页对象
	 * @param menuIds 菜单数组
	 * @return 分页对象
	 */
	public Page<AcMenuForm> getMenusNotInMenuIds(Page<AcMenuForm> page, Long[] menuIds){
		if( menuIds != null && menuIds.length > 0){
			// 建立新的分页对象
			Page<AcMenu> pg = PageUtils.newPageInstance(page);
			
			String hql = "from AcMenu ps where ps.isLeaf=" + "1 ";
			String condition = HqlUtils.buildAndCondition("ps", "menuId", menuIds);
			hql += "and ";
			hql += condition;
			
			pg = acMenuDao.findPage(pg, hql);
			
			// 转换为Form对象列表并赋值到原分页对象中
			List<AcMenuForm> list = AcMenuConverter.convertToForm(pg.getResult());
			PageUtils.copy(pg, list, page);
			return page;
			
		}
		return null;
	}
	
	/**
	 * 获取用户具有权限的菜单id数组
	 * @param userId
	 * @return 菜单id数组
	 */
	public Long[] getMenuIdsOwnedByUser(Long userId){
		if(userId != null){
			Long[] funcIds = acRoleService.getFuncIdsByUserId(userId);
			Long[] menuIds = this.getAllRelatedMenuIds(funcIds);
			return menuIds;
		}
		return null;
	}
}
